package com.originskyseed.platform.role.provider;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboService;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Component;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.originskyseed.platform.common.api.constant.RedisKeyConstans;
import com.originskyseed.platform.core.base.BasePage;
import com.originskyseed.platform.core.redis.util.RedisUtil;
import com.originskyseed.platform.core.util.bean.PrimaryKeyGeneratorUtil;
import com.originskyseed.platform.role.mapper.MenuMapper;
import com.originskyseed.platform.role.mapper.RoleMapper;
import com.originskyseed.platform.role.mapper.RoleRelMenuMapper;
import com.originskyseed.platform.role.model.Menu;
import com.originskyseed.platform.role.model.Role;
import com.originskyseed.platform.role.model.RoleRelMenu;
import com.originskyseed.platform.role.service.IMenuService;

/**
 * 菜单Service实现类
 * 
 * @author LiangMingHui
 *
 */
@DubboService
@Component("menuService")
public class MenuServiceImpl implements IMenuService {

	@Resource
	private MenuMapper menuMapper;

	@Resource
	private RoleRelMenuMapper roleRelMenuMapper;

	@Resource
	private RoleMapper roleMapper;

	/**
	 * deleteByPrimaryKey
	 * 
	 * @param id
	 * @return
	 * @throws Exception
	 */
	@Override
	public int deleteByPrimaryKey(String id) throws Exception {
		return this.menuMapper.deleteByPrimaryKey(id);
	}

	/**
	 * deleteByPrimaryKeys
	 * 
	 * @param ids
	 * @return
	 * @throws Exception
	 */
	@Override
	public int deleteByPrimaryKeys(List<String> ids) throws Exception {
		return this.menuMapper.deleteByPrimaryKeys(ids);
	}

	/**
	 * insert
	 * 
	 * @param record
	 * @return
	 * @throws Exception
	 */
	@Override
	public int insert(Menu record) throws Exception {
		if (StringUtils.isBlank(record.getId())) {
			record.setId(PrimaryKeyGeneratorUtil.getInstance().getRandomKey());
		}
		record.setCreateTime(new Date());
		return this.menuMapper.insert(record);
	}

	/**
	 * 插入菜单与权限表
	 * 
	 * @param record
	 * @return
	 * @throws Exception
	 */
	@Override
	public int insertSelective(Menu record) throws Exception {
		if (StringUtils.isBlank(record.getId())) {
			record.setId(PrimaryKeyGeneratorUtil.getInstance().getRandomKey());
		}
		record.setCreateTime(new Date());
		// 把权限增加给系统管理员
		Map<String, Object> map = new HashMap<>();
		map.put("code", "SYSTEM_ADMIN");
		Role role = roleMapper.selectByCode(map);
		if (role != null) {
			RoleRelMenu roleRelPermission = new RoleRelMenu();
			roleRelPermission.setId(PrimaryKeyGeneratorUtil.getInstance().getRandomKey());
			roleRelPermission.setPermissionId(record.getId());
			roleRelPermission.setRoleId(role.getId());
			roleRelPermission.setCreateTime(new Date());
			this.roleRelMenuMapper.insertSelective(roleRelPermission);
		}

		return this.menuMapper.insertSelective(record);
	}

	/**
	 * selectByPrimaryKey
	 * 
	 * @param id
	 * @return
	 * @throws Exception
	 */
	@Override
	public Menu selectByPrimaryKey(String id) throws Exception {
		return this.menuMapper.selectByPrimaryKey(id);
	}

	/**
	 * updateByPrimaryKeySelective
	 * 
	 * @param record
	 * @return
	 * @throws Exception
	 */
	@Override
	public int updateByPrimaryKeySelective(Menu record) throws Exception {
		record.setUpdateTime(new Date());
		return this.menuMapper.updateByPrimaryKeySelective(record);
	}

	/**
	 * updateByPrimaryKeySelective
	 *
	 * @param record
	 * @return
	 * @throws Exception
	 */
	@Override
	public int updateByPrimaryKeySelective1(Menu record) throws Exception {
		record.setUpdateTime(new Date());
		return this.menuMapper.updateByPrimaryKeySelective(record);
	}

	/**
	 * 更新菜单和权限
	 * 
	 * @param record
	 * @return
	 * @throws Exception
	 */
	@Override
	public int updateByPrimaryKey(Menu record) throws Exception {
		record.setUpdateTime(new Date());
		return this.menuMapper.updateByPrimaryKey(record);
	}

	/**
	 * 获取一级菜单列表
	 * 
	 * @param userId
	 * @return
	 * @throws Exception
	 */
	@Override
	public List<Menu> selectFirstLevelMenus(String userId, Map<String, Object> params) throws Exception {
		// 根据code获取一级菜单
		List<Menu> menuList = this.menuMapper.selectFirstLevelMenus(params);
		return this.selectByPermissionMenu(userId, menuList);
	}

	/**
	 * 根据code和用户id获取用户拥有权限的子菜单
	 * 
	 * @param code
	 * @param userId
	 * @return
	 * @throws Exception
	 */
	public List<Menu> selectFirstLevelMenusByUser(String code, String userId) throws Exception {
		return this.menuMapper.selectFirstLevelMenusByUser(code, userId);
	}

	/**
	 * 根据角色code查询用户的一级菜单
	 * 
	 * @param roleCode
	 * @return
	 * @throws Exception
	 */
	public List<Menu> selectFirstMenuByRoleCode(String roleCode) throws Exception {
		String key = RedisKeyConstans.getTenantCodeAndRedisKey(RedisKeyConstans.ROLE_MENU_KEY) + roleCode;
		List<Menu> menuList = (List<Menu>) RedisUtil.getInstance().getForObject(key);
		if (menuList == null || menuList.size() == 0) {
			loadRoleMenuAddRedis();
			menuList = (List<Menu>) RedisUtil.getInstance().getForObject(key);
		}
		return menuList;
	}

	/**
	 * 获取二级菜单列表
	 * 
	 * @param userId
	 * @param params
	 * @return
	 * @throws Exception
	 */
	@Override
	public List<Menu> selectSecondLevelMenus(String userId, Map<String, Object> params) throws Exception {
		List<Menu> menuList = this.menuMapper.selectSecondLevelMenus(params);
		return this.selectByPermissionMenu(userId, menuList);
	}

	/**
	 * 获取菜单树
	 * 
	 * @return
	 * @throws Exception
	 */
	@Override
	public JSONArray selectMenuTree(String mallId) throws Exception {
		JSONArray result = new JSONArray();

		// 获取所有菜单列表
		List<Menu> menuList = this.menuMapper.selectAllMenus(mallId);

		// 追加菜单树节点
		for (Menu menu : menuList) {
			JSONObject jsonObject = new JSONObject();
			jsonObject.put("id", menu.getId());
			jsonObject.put("pid", menu.getParentId());
			jsonObject.put("name", menu.getName());
			if (menu.getParentId() == null || menu.getParentId().equals("")) {
				jsonObject.put("open", true);
			} else {
				jsonObject.put("open", false);
			}

			result.add(jsonObject);
		}

		return result;
	}

	/**
	 * 分页查询菜单列表
	 * 
	 * @param params
	 * @param page
	 * @return
	 * @throws Exception
	 */
	@Override
	public BasePage<Menu> selectListByPage(Map<String, Object> params, BasePage<Menu> page) throws Exception {
		params.put("page", page);
		List<Menu> list = this.menuMapper.selectListByPage(params);
		page.setResults(list);
		return page;
	}

	/**
	 * 查询列表
	 *
	 * @param record
	 * @return
	 * @throws Exception
	 */
	@Override
	public List<Menu> selectList(Menu record) throws Exception {
		return this.menuMapper.selectList(record);
	}

	/**
	 * 获取三级菜单列表
	 *
	 * @param userId
	 * @param params
	 * @return
	 * @throws Exception
	 */
	@Override
	public List<Menu> selectThirdLevelMenus(String userId, Map<String, Object> params) throws Exception {
		List<Menu> menuList = this.menuMapper.selectThirdLevelMenus(params);
		return this.selectByPermissionMenu(userId, menuList);
	}

	/**
	 * 获取全部菜单
	 * 
	 * @return
	 * @throws Exception
	 */
	@Override
	public List<Menu> selectAllMenu(String mallId) throws Exception {
		return this.menuMapper.selectAllMenus(mallId);
	}

	@Override
	public JSONArray selectMenuTreeList(String mallId) throws Exception {
		// 获取所有菜单列表
		List<Menu> menuList = this.menuMapper.selectAllMenus(mallId);
		List<Menu> parentList = new ArrayList<Menu>();
		for (Menu menu : menuList) {
			if (StringUtils.isBlank(menu.getParentId())) {
				parentList.add(menu);
			}
		}
		for (Menu menu : parentList) {
			menuList.remove(menu);
		}
		// 递归构建
		return build2Tree(menuList, parentList);
	}

	public List<Menu> selectMenuByRoleCode(String roleCode) throws Exception {
		return this.menuMapper.selectFirstMenuByRoleCode(roleCode);
	}

	public void loadRoleMenuAddRedis() throws Exception {
		Role role = new Role();
		List<Role> roleList = this.roleMapper.selectList(role);
		for (Role role1 : roleList) {
			List<Menu> menuList = this.menuMapper.selectFirstMenuByRoleCode(role1.getCode());
			String key = RedisKeyConstans.getTenantCodeAndRedisKey(RedisKeyConstans.ROLE_MENU_KEY) + role1.getCode();
			RedisUtil.getInstance().setForObject(key, menuList);
		}
	}

	/**
	 * 根据角色查询菜单
	 * 
	 * @param ids
	 * @return
	 * @throws Exception
	 */
	public List<Menu> selectMenuByRoleId(List<String> ids) throws Exception {
		return this.menuMapper.selectMenuByRoleId(ids);
	}

	/**
	 * 根据用户标识获取权限列表
	 *
	 * @param userId
	 * @return
	 * @throws Exception
	 */
	@Override
	public List<Menu> selectByUserId(String userId) throws Exception {
		return this.menuMapper.selectByUserId(userId);
	}

	/**
	 * 查询
	 * 
	 * @param sysType
	 * @return
	 * @throws Exception
	 */
	@Override
	public String selectParentIdBySysType(int sysType) throws Exception {
		return this.menuMapper.selectParentIdBySysType(sysType);
	}

	/**
	 * selectButtonLevelByCode
	 * 
	 * @param permissionCode
	 * @param roleId
	 * @return
	 * @throws Exception
	 */
	public List<Menu> selectButtonLevelByCode(@Param("permissionCode") String permissionCode, @Param("roleId") String roleId) throws Exception {
		return this.menuMapper.selectButtonLevelByCode(permissionCode, roleId);
	}

	/**
	 * 构建树
	 *
	 * @param list       包含所有数据
	 * @param parentList 只包含根节点或父节点数据
	 * @return
	 */
	private JSONArray build2Tree(List<Menu> list, List<Menu> parentList) {
		JSONArray ary = new JSONArray();
		if (!list.isEmpty() && !parentList.isEmpty()) {
			JSONObject obj;
			// 移除父节点
			list.removeAll(parentList);
			List<Menu> childList;
			for (Menu menu : parentList) {
				obj = new JSONObject();
				obj.put("id", menu.getId());
				obj.put("pid", menu.getParentId());
				obj.put("name", menu.getName());
				obj.put("sysType",menu.getSysType());
				// 查找子节点
				childList = findChildren(list, menu);
				if (hasChildren(childList)) {
					obj.put("children", build2Tree(list, childList));
				}
				ary.add(obj);
			}
		}
		return ary;
	}

	/**
	 * 查找当前父节点下的子节点数据
	 *
	 * @param list 去除父节点的所有数据
	 * @param menu 父节点
	 * @return
	 */
	private List<Menu> findChildren(List<Menu> list, Menu menu) {
		List<Menu> childList = new ArrayList<Menu>();
		if (!list.isEmpty()) {
			for (Menu cms : list) {
				if (cms.getParentId().equals(menu.getId())) {
					childList.add(cms);
				}
			}
		}
		return childList;
	}

	private boolean hasChildren(List<Menu> list) {
		return list.size() > 0 ? true : false;
	}

	/**
	 * 根据改用户对应的权限查询出目录
	 *
	 * @param userId
	 * @param menuList
	 * @return
	 * @throws Exception
	 */
	public List<Menu> selectByPermissionMenu(String userId, List<Menu> menuList) throws Exception {
		List<Menu> returnMenuList = new ArrayList<>();
		// 查询出该用户的所有权限
		List<Menu> menuList1 = this.menuMapper.selectByUserId(userId);
		for (Menu menu : menuList) {
			// 判断菜单的code是否等于权限的code
			for (Menu menu1 : menuList1) {
				if (menu.getId().equals(menu1.getId())) {
					returnMenuList.add(menu);
					break;
				}
			}
		}
		return returnMenuList;
	}
}
